package com.deer.wms.ware.task.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.deer.wms.busine.tactic.model.WaveTacticDianshang;
import com.deer.wms.busine.tactic.model.WaveTacticDianshangCriteria;
import com.deer.wms.busine.tactic.model.WaveTacticDianshangDto;
import com.deer.wms.busine.tactic.service.WaveTacticDianshangService;
import com.deer.wms.busine.tactic.service.WaveTacticService;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.inventory.model.Inventory.Inventory;
import com.deer.wms.inventory.model.Inventory.InventorySelectDto;
import com.deer.wms.inventory.service.InventoryService;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.service.SuperServiceImpl;
import com.deer.wms.project.root.util.*;
import com.deer.wms.system.manage.constant.SystemManageConstant;
import com.deer.wms.system.manage.model.ware.WareInfo;
import com.deer.wms.system.manage.service.CodeRuleService;
import com.deer.wms.system.manage.service.WareInfoService;
import com.deer.wms.ware.task.config.StrategyErpService;
import com.deer.wms.ware.task.constant.WareTaskConstant;
import com.deer.wms.ware.task.dao.WaveMasterMapper;
import com.deer.wms.ware.task.erp.UpdatePPF;
import com.deer.wms.ware.task.model.SO.SoDetail;
import com.deer.wms.ware.task.model.SO.SoMaster;
import com.deer.wms.ware.task.model.SO.SoMasterCriteria;
import com.deer.wms.ware.task.model.Wave.WaveDetail;
import com.deer.wms.ware.task.model.Wave.WaveMaster;
import com.deer.wms.ware.task.model.Wave.WaveMasterCriteria;
import com.deer.wms.ware.task.model.Wave.WaveMasterDto;
import com.deer.wms.ware.task.model.out.OutDetail;
import com.deer.wms.ware.task.model.out.OutMaster;
import com.deer.wms.ware.task.model.pickTask.PickTask;
import com.deer.wms.ware.task.model.pushErp.beasAssist.BaseAssist;
import com.deer.wms.ware.task.service.SoDetailService;
import com.deer.wms.ware.task.service.SoMasterService;
import com.deer.wms.ware.task.service.WaveDetailService;
import com.deer.wms.ware.task.service.WaveMasterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.activation.DataHandler;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static com.deer.wms.project.root.util.CollectionUtils.convertMap;

/**
 * @author ll
 * @since 2020/02/02
 */
@Service
@Transactional
public class WaveMasterServiceImpl extends SuperServiceImpl<WaveMasterMapper, WaveMaster> implements WaveMasterService {

    @Autowired
    private WaveTacticService waveTacticService;
    @Autowired
    private SoMasterService soMasterService;
    @Autowired
    private WaveDetailService waveDetailService;
    @Autowired
    private WareInfoService wareInfoService;
    @Autowired
    private WaveMasterMapper waveMasterMapper;
    @Autowired
    private WaveTacticDianshangService waveTacticDianshangService;
    @Autowired
    private CodeRuleService codeRuleService;


    @Autowired
    private InventoryService inventoryService;

    @Autowired
    private SoDetailService soDetailService;
    @Value("${wave.start}")
    //先發配件
    private Integer start;

    /**
     * 生成波次 <p>
     * 不同的仓库，波次策略不一样
     *
     * @return boolean
     */
    @Override
    public boolean generateWaves() {
        String now = DateUtils.getNowDateTimeString();

        // 查询激活的波次策略
        WaveTacticDianshangCriteria criteria = new WaveTacticDianshangCriteria();
        criteria.setState(1);
        List<WaveTacticDianshangDto> tactics = waveTacticDianshangService.findList(criteria);

        if (tactics == null || tactics.size() == 0) {
            System.out.println("没有激活的波次策略！");
            return false;
        }

        // 根据每条策略生成波次
        for (WaveTacticDianshang waveTactic : tactics) {
            //根据波次策略中的条件
            SoMasterCriteria soMasterCriteria = generateSoMasterCriteria(waveTactic);
            List<SoMaster> soMasters = soMasterService.findSoByWave(soMasterCriteria);

            //线程每时每刻都在刷新，同一个波次策略生成波次只能在设置的最大分钟数内，否则该策略的下一个波次
            Integer maxTime = waveTactic.getMaxWaitTime();
            //判断是否已生成最新的波次
            WaveMaster last = waveMasterMapper.getLast(waveTactic.getWaveTacticCode());
            String nowTime = DateUtils.getNowDateTimeString();
            //如果波次已存在，获取波次的生成时间，如果波次未生成，获取当前时间
            String lastTime = last == null ? nowTime : last.getCreateTime();
            //获取时间差值，分别处理
            Long durationTime = DateUtils.getMin(lastTime, nowTime);
            if (last != null && durationTime >= maxTime) {
                //超出等待时间，状态改为待拣货
                last.setState(1);
                this.updateById(last);
            }
            if (last != null && last.getTotalBillCount() >= waveTactic.getSoCountLimit()) {
                //超过SO订单数，不能再合波次，状态改为待拣货
                last.setState(1);
                this.updateById(last);
            }
            if (last != null && last.getTotalSkuCount() >= waveTactic.getItemCount()) {
                //超过SKU数，不能再合波次，状态改为待拣货
                last.setState(1);
                this.updateById(last);
            }
            if (soMasters.size() > 0) {
                //该策略第一次生成  或者 该波次要生成下一个波次
                if (waveTactic.getLastTime() == null || durationTime >= maxTime || last == null) {
                    //生成新的波次
                    WareInfo ware = wareInfoService.getById(waveTactic.getWareId());
                    WaveMaster waveMaster = new WaveMaster();
                    waveMaster.setCreateTime(now);
                    waveMaster.setCode(BillNoUtils.generateWaveCode(waveTactic.getWareId()));
                    waveMaster.setWareId(waveTactic.getWareId());
                    waveMaster.setWareName(ware.getWareName());
                    waveMaster.setWaveTacticCode(waveTactic.getWaveTacticCode());
                    waveMaster.setTotalSkuCount(0);
                    waveMaster.setTotalBillCount(0);

                    soMasters:
                    for (SoMaster soMaster : soMasters) {
                        Integer count = waveMasterMapper.countSku(waveMaster.getWaveId(), soMaster.getSoMasterId()).size();
                        if (count > waveTactic.getItemCount() || waveMaster.getTotalBillCount() >= waveTactic.getSoCountLimit()) {
                            if (waveMaster.getWaveId() != null) {
                                waveMaster.setState(1);
                                this.updateById(waveMaster);
                            }
                        } else {
                            waveMaster.setTotalSkuCount(count);
                            waveMaster.setTotalBillCount(waveMaster.getTotalBillCount() + 1);
                            if (waveMaster.getWaveId() == null) {
                                waveTactic.setLastTime(nowTime);
                                waveTacticDianshangService.updateById(waveTactic);
                                save(waveMaster);
                            } else {
                                this.updateById(waveMaster);
                            }
                            WaveDetail waveDetail = new WaveDetail();
//                            waveDetail.setSoMasterId(soMaster.getSoMasterId());
                            waveDetail.setWaveMasterId(waveMaster.getWaveId());
                            waveDetailService.save(waveDetail);
                        }
                    }
                } else {
                    //不需要生成新的波次
                    List<WaveDetail> list = waveDetailService.getByMasterId(last.getWaveId());
                    Integer soCount = list.size() - 1;
                    soMasters:
                    for (SoMaster soMaster : soMasters) {
                        soCount += 1;
                        Integer count = waveMasterMapper.countSku(last.getWaveId(), soMaster.getSoMasterId()).size();
                        if (count > waveTactic.getItemCount() || soCount >= waveTactic.getSoCountLimit()) {
                            //超过SKU限制
                            last.setState(1);
                        } else {
                            WaveDetail waveDetail = new WaveDetail();
//                            waveDetail.setSoMasterId(soMaster.getSoMasterId());
                            waveDetail.setWaveMasterId(last.getWaveId());
                            waveDetailService.save(waveDetail);
                            last.setTotalSkuCount(count);
                            last.setTotalBillCount(last.getTotalBillCount() + 1);
                        }
                        this.updateById(last);
                    }
                }
            }
        }
        return true;
    }

    @Override
    public void waveState() {
        //找到状态在 0(订单接收中) ~ 4(发运完成) 之间的波次
        List<WaveMaster> list = findByStateNo0();

        waveMaster:
        for (WaveMaster waveMaster : list) {
            //已分配  正在拣货中的SO数量
            Integer count4 = soMasterService.findCountByWaveIdAndState(waveMaster.getWaveId(), WareTaskConstant.SO_STATE_ASSIGNED);
            //拣货完成SO数量
            Integer count6 = soMasterService.findCountByWaveIdAndState(waveMaster.getWaveId(), WareTaskConstant.SO_STATE_PICKED);
            //复核完成的SO数量
            Integer count7 = soMasterService.findCountByWaveIdAndState(waveMaster.getWaveId(), WareTaskConstant.SO_STATE_CHECKED);
            //发运完成的SO数量
            Integer count8 = soMasterService.findCountByWaveIdAndState(waveMaster.getWaveId(), WareTaskConstant.SO_STATE_OUTED);

            //拣货中的为0 拣货完成的大于0
            if (count4 == 0 && count6 > 0) {
                //拣货完成
                waveMaster.setState(WareTaskConstant.WAVE_STATE_PICKED);
                this.updateById(waveMaster);
            }

            //拣货完成的为0 复核完成的大于0
            if (count6 == 0 && count7 > 0) {
                //播种完成 || 复核完成
                waveMaster.setState(WareTaskConstant.WAVE_STATE_CHECKED);
                this.updateById(waveMaster);
            }

            //复核完成的为0 发运完成的大于0
            if (count7 == 0 && count8 > 0) {
                //发运完成
                waveMaster.setState(WareTaskConstant.WAVE_STATE_SEND);
                this.updateById(waveMaster);
            }
        }
    }

    @Override
    public List<WaveMaster> findByState(Integer state) {
        return waveMasterMapper.findByState(state);
    }


    @Override
    public List<WaveMaster> findByStateNo0() {
        return waveMasterMapper.findByStateNo0();
    }

    @Override
    public List<WaveMasterDto> findList(WaveMasterCriteria criteria) {
//        QueryWrapper<SoMaster> queryWrapper = new QueryWrapper();
//        queryWrapper.and(ObjectUtil.isNotEmpty(criteria.getKeyWords()), w -> w
//                .or().like("wave_code", criteria.getKeyWords())
//                .or().like("trade_no", criteria.getKeyWords())
//        );
//        Set<String> waveCodes = soMasterService.list(queryWrapper).stream().map(SoMaster::getWareCode).collect(Collectors.toSet());

        return waveMasterMapper.findList(criteria);
    }

    @Override
    public List<WaveMasterDto> allotWave(WaveMasterCriteria criteria) {
        return waveMasterMapper.allotWave(criteria);
    }

    @Override
    public WaveMaster mergeSo(List<SoMaster> soMasterDtoList, CurrentUser currentUser, List<SoDetail> soDetailList, String remake) {
        //Stpe0.赋值部门Id
        Map<String, SoMaster> masterMap = convertMap(soMasterDtoList, SoMaster::getBillNo);
        for (SoDetail soDetail : soDetailList) {
            soDetail.setDeptId(masterMap.get(soDetail.getBillNo()).getDeptId());
        }


        WaveMaster waveMaster = null;
        List<WaveDetail> waveDetailList = new ArrayList<>();
        //汇总出库任务明细，统一处理
//        List<SoDetail> soDetailList = new ArrayList<>();
        List<SoMaster> soMasterList = new ArrayList<>();
        //Step1.根据某一条出库任务生成波次
        for (SoMaster soMasterDto : soMasterDtoList) {
            //只会执行一次
            if (waveMaster == null) {
                waveMaster = new WaveMaster();
                //波次号
                waveMaster.setCode(codeRuleService.generateCodeByRedis(SystemManageConstant.CODE_RULE_WAVE));
                waveMaster.setRemake(remake);
                //创建人 时间
                waveMaster.setAllotUserId(currentUser.getUserId());
                waveMaster.setAllotUserName(currentUser.getUserName());
                waveMaster.setAllotTime(DateUtil.now());
                waveMaster.setCreateTime(DateUtil.now());
                //状态(新建) 仓库
                waveMaster.setState(WareTaskConstant.WAVE_STATE_PROCESSING);
                //部门id
                waveMaster.setDeptId(soMasterDto.getDeptId());
                waveMaster.setWareId(soMasterDto.getWareId());
                waveMaster.setWareName(soMasterDto.getWareName());
                //单据号数和SKU数
                waveMaster.setTotalBillCount(soMasterDtoList.size());
            }
            //出库任务信息更新：记录其关联的波次编码，修改状态
//            SoMaster soMaster = soMasterService.getById(soMasterDto.getSoMasterId());
            // todo 把历史波次明细插入到字段中逗号分割，方便后期查询  2022.08.06徐鹏宇
            soMasterDto.setWaveCode(waveMaster.getCode());
            //当前波次合单人
            soMasterDto.setNowWaveUserName(currentUser.getUserName());
            this.createAncestral(soMasterDto, waveMaster.getCode(), currentUser.getUserName());
            soMasterDto.setState(WareTaskConstant.SO_STATE_PROCESSING);
            //添加进明细集合，下一步骤一并处理
            soMasterList.add(soMasterDto);
        }
        //todo 出库任务单号，入库任务单号，履约号集合转换成字符串set到波次任务表中，方便后期查询 20220806
        this.createWaveAncestral(soMasterDtoList, waveMaster);

        //

        this.save(waveMaster);
        Map<String, List<SoMaster>> soMasterMap = soMasterDtoList.stream().collect(Collectors.groupingBy(SoMaster::getBillNo));
        // 这里是不是可以增加一层把已经合并的波次信息剔除--张宇
        //itemCode,红蓝字分组
        Map<String, List<SoDetail>> map = soDetailList.stream().collect(Collectors.groupingBy(SoDetail::getItemCode));
        Set<String> keys = map.keySet();
        List<SoDetail> detailList = new ArrayList<>();
        List<UpdatePPF> ppfList = new ArrayList<>();
        List<WaveDetail> saveWaveDetails = new ArrayList<>();
        //行号
        int rowNum = 1;
        for (String key : keys) {
            List<SoDetail> soDetails = map.get(key);
            //新增
            WaveDetail waveDetail = new WaveDetail(soDetails.listIterator().next());
            //波次单信息
            waveDetail.setWaveMasterId(waveMaster.getWaveId());
            waveDetail.setWaveCode(waveMaster.getCode());
            waveDetail.setWareId(waveMaster.getWareId());
            waveDetail.setWareName(waveMaster.getWareName());
            double qty = soDetails.stream().mapToDouble(soDetail -> soDetail.getOrderQuantity() - soDetail.getAllottedQuantity()).sum();
            waveDetail.setQuantity(qty);
            waveDetail.setAllottedQuantity(0.0);
            waveDetail.setPickQuantity(0.0);
            waveDetail.setWaveDetailCode(waveMaster.getCode() + "*" + rowNum);
            rowNum++;
            saveWaveDetails.add(waveDetail);
        }
        waveDetailService.saveBatch(saveWaveDetails);
        Map<String, WaveDetail> waveDetailMap = convertMap(saveWaveDetails, WaveDetail::getItemCode);

        for (SoDetail soDetail : soDetailList) {
            SoMaster soMaster = masterMap.get(soDetail.getBillNo());
            double notAllQty = soDetail.getOrderQuantity() - soDetail.getAllottedQuantity();
            //小于0
            if (notAllQty <= 0) {
                continue;
            }
            if (ObjectUtil.isNotEmpty(soMaster) && soMaster.getBillType() == 88) {
                UpdatePPF updatePPF = new UpdatePPF();
                updatePPF.setRowIndex(soDetail.getBomSplit());
                updatePPF.setBillId(soDetail.getErpBillId());
                updatePPF.setCommitQty(soDetail.getOrderQuantity() - soDetail.getAllottedQuantity());
                ppfList.add(updatePPF);
            }
            String itemCode = soDetail.getItemCode();
            WaveDetail waveDetail = waveDetailMap.get(itemCode);
            if (ObjectUtil.isNotEmpty(waveDetail)) {
                soDetail.setWaveDetailId(waveDetail.getWaveDetailId());
            }

        }



        waveMaster.setTotalSkuCount(keys.size());
        this.updateById(waveMaster);
        soMasterService.updateBatchById(soMasterList);
        soDetailService.updateBatchById(soDetailList);
        if (soMasterDtoList.listIterator().next().getBillType() == 88 &&ObjectUtil.isNotEmpty(ppfList)) {
            //修改冻结数量
            try {
                CompletableFuture.runAsync(() -> {
                    List<UpdatePPF> updatePPFS = ppfList.stream().filter(item -> item.getCommitQty() != 0).collect(Collectors.toList());
                    pushErpService.UpdatePPFeedAssignedQty(updatePPFS);
                });
            } catch (Exception e) {

                System.out.println(e);
            }
        }
        return waveMaster;
    }

    @Override
    public List<SoDetail> onSoMaster(String waveCode, String itemCode) {
        return baseMapper.onSoMaster(waveCode, itemCode);
    }

    @Override

    public void split(String waveCode) {
        //波次任务单
        WaveMaster waveMaster = getOne(new QueryWrapper<WaveMaster>().eq("code", waveCode));
        //波次明细
        List<WaveDetail> waveDetails = waveDetailService.list(new QueryWrapper<WaveDetail>().eq("wave_code", waveCode));
        List<SoMaster> soMasters = soMasterService.list(new QueryWrapper<SoMaster>().eq("wave_code", waveCode));
        //制空波次单code
        for (SoMaster soMaster : soMasters) {
            soMaster.setWaveCode(null);
            soMaster.setState(12);
        }
        //修改波次明细行
        soMasterService.updateBatchById(soMasters);

        if (ObjectUtil.isEmpty(waveDetails)) {
            removeById(waveMaster.getWaveId());
            return;
        }
        //波次id
        List<Integer> waveDetailId = waveDetails.stream().map(WaveDetail::getWaveDetailId).collect(Collectors.toList());
        //任务单明细
        List<SoDetail> soDetails = soDetailService.list(new QueryWrapper<SoDetail>().in("wave_detail_id", waveDetailId));
        //过滤需要删除的波次明细行
        List<Integer> removeIds = waveDetails.stream().filter(item -> item.getState() == 0).map(WaveDetail::getWaveDetailId).collect(Collectors.toList());
        List<UpdatePPF> ppf = new ArrayList<>();

        //制空任务单id
        for (SoDetail soDetail : soDetails) {
            if (soMasters.listIterator().next().getBillType() == 88) {
                UpdatePPF updatePPF = new UpdatePPF();
                updatePPF.setRowIndex(soDetail.getBomSplit());
                updatePPF.setBillId(soDetail.getErpBillId());
                updatePPF.setCommitQty(0.00 - soDetail.getOrderQuantity() + soDetail.getAllottedQuantity());
                ppf.add(updatePPF);
            }
            soDetail.setWaveDetailId(null);
        }
        for (WaveDetail waveDetail : waveDetails) {
            waveDetail.setQuantity(waveDetail.getAllottedQuantity());
            waveDetail.setState(WareTaskConstant.WAVE_STATE_ALL_ALOT);
        }
        //修改状态，数量
        waveDetailService.updateBatchById(waveDetails);
        //修改任务单明细行
        soDetailService.updateBatchById(soDetails);

        //修改波次单状态，波次单明细行
        waveDetailService.updateTotalSkuCount(waveMaster);
        //删除初始化状态的明细行
        waveDetailService.removeByIds(removeIds);


        //补货异常
            CompletableFuture.runAsync(() -> {
                List<UpdatePPF> updatePPFS = ppf.stream().filter(item -> item.getCommitQty() != 0).collect(Collectors.toList());
                pushErpService.UpdatePPFeedAssignedQty(updatePPFS);
            });



    }

    /***
     * 同步拉取先发配件出库
     * @param billNos
     */
    @Override
    public List<SoDetail> robAndStart(List<String> billNos) {
        List<SoDetail> allSoDetails = new ArrayList<>();
        List<SoMaster> soMasters = soMasterService.list(new QueryWrapper<SoMaster>().in("bill_no", billNos));
        Map<String, SoMaster> soMap = convertMap(soMasters, SoMaster::getBillNo);
        List<SoDetail> newSoDetails = soDetailService.syncCurrentData(soMasters);
        if (ObjectUtil.isEmpty(newSoDetails)) {
            newSoDetails = new ArrayList<>();
        }
        List<SoDetail> oldSoDetails =  soDetailService.list(new QueryWrapper<SoDetail>().in("bill_no", billNos));

        if (ObjectUtil.isEmpty(oldSoDetails)) {
            oldSoDetails = new ArrayList<>();
        }
        //对应波次详情
        //老单子新单子合并
        allSoDetails.addAll(oldSoDetails);
        allSoDetails.addAll(newSoDetails);
        //行号可能重复，不能作为唯一条件去重
        Map<SoDetail, SoDetail> newMap = newSoDetails.stream()
                .collect(Collectors.toMap(item -> item, soDetail -> soDetail, (oldValue, newValue) -> newValue));
        //新单子老单子合并
        Map<SoDetail, SoDetail> oldMap = oldSoDetails.stream()
                .collect(Collectors.toMap(item -> item, soDetail -> soDetail, (oldValue, newValue) -> newValue));
        //3.根据明细行去获取
        soDetailService.contrastSoDetail(allSoDetails, newMap, oldMap);
        //处理先发配件物料
        List<SoDetail> newSo =  soDetailService.list(new QueryWrapper<SoDetail>().in("bill_no", billNos));
        Set<String> itemCodes = newSo.stream().map(SoDetail::getItemCode).collect(Collectors.toSet());

        List<Inventory> inventoryList = inventoryService.list(new QueryWrapper<Inventory>()
                .in("item_code", itemCodes)
                .eq("erp_area_id", start)
                //先发配件库
                .isNotNull("mto_no")
                //直发虚仓仓库id待定
                .notIn("cell_code", 285000, 285333)
        );
        Map<String, List<Inventory>> invMap = inventoryList.stream().collect(Collectors.groupingBy(item -> item.getItemCodeAndMto()));

        if (ObjectUtil.isEmpty(invMap)) {
            return newSo;
        }
        List<OutDetail> outDetails = new ArrayList<>();
        List<UpdatePPF> ppfList = new ArrayList<>();

        //分配先发配件
        for (SoDetail soDetail : newSo) {

            //Step2.生成拣货任务
            double remainAllotQty;
            //有预分配数量则取预分配数量，没有则全部分配
            remainAllotQty = soDetail.getOrderQuantity() - soDetail.getAllottedQuantity();
            if (remainAllotQty <= 0) {
                continue;
            }
            String tradeNo = soMap.get(soDetail.getBillNo()).getTradeNo();
            List<Inventory> invs = inventoryList.stream().filter(item -> item.getItemCode().equals(soDetail.getItemCode()) && tradeNo.contains(item.getBatchName())).collect(Collectors.toList());
            if (ObjectUtil.isEmpty(invs)) {
                continue;
            }
            for (Inventory inv : invs) {
                double canBeQuantity = inv.getQuantity() - inv.getAllotQuantity() - inv.getFreezeQuantity();
                if (canBeQuantity <= 0) {
                    continue;
                }
                //出库
                OutDetail outDetail = new OutDetail();
                BeanUtils.copyProperties(soDetail, outDetail);
                outDetail.setMtoNo(soMap.get(soDetail.getBillNo()).getMergeNo());
                outDetail.setBatchName(inv.getBatchName());
                outDetail.setErpAreaId(inv.getErpAreaId());
                outDetail.setMtoNo(inv.getBatchName());
                //回传分配数
                UpdatePPF updatePPF = new UpdatePPF();
                updatePPF.setBillId(soDetail.getErpBillId());
                updatePPF.setRowIndex(soDetail.getBomSplit());

                if (canBeQuantity >= remainAllotQty) {
                    outDetail.setDeliveryQuantity(remainAllotQty);
                    outDetails.add(outDetail);
                    updatePPF.setCommitQty( remainAllotQty);
                    ppfList.add(updatePPF);
                    outDetail.setDeliveryQuantity(remainAllotQty);
                    soDetail.setAllottedQuantity(soDetail.getAllottedQuantity() + remainAllotQty);
                    soDetail.setPickQuantity(soDetail.getPickQuantity() + remainAllotQty);
                    soDetail.setDeliveryQuantity(soDetail.getDeliveryQuantity() + remainAllotQty);
                    inv.setTransRatio(1.0);
                    inv.setQuantity(inv.getQuantity() - remainAllotQty);
//                    inventoryService.updateById(inv);
                    //分配完成直接跳出循环
                    //记录状态
                    if (ObjectUtil.equal(soDetail.getOrderQuantity(), soDetail.getAllottedQuantity())) {
                        soDetail.setState(WareTaskConstant.WAVE_STATE_ALL_ALOT);
                    } else {
                        soDetail.setState(WareTaskConstant.WAVE_STATE_PICKING);
                    }
                    break;
                } else {
                    //2)可分配数量不够完全分配  则将可分配数量全部分配出去
                    outDetail.setDeliveryQuantity(canBeQuantity);
                    outDetails.add(outDetail);
                    updatePPF.setCommitQty( canBeQuantity);
                    ppfList.add(updatePPF);
                    soDetail.setAllottedQuantity(soDetail.getAllottedQuantity() + canBeQuantity);
                    soDetail.setPickQuantity(soDetail.getPickQuantity() + canBeQuantity);
                    soDetail.setDeliveryQuantity(soDetail.getDeliveryQuantity() + canBeQuantity);

                    if (ObjectUtil.equal(soDetail.getOrderQuantity(), soDetail.getAllottedQuantity())) {
                        soDetail.setState(WareTaskConstant.WAVE_STATE_ALL_ALOT);
                    } else {
                        soDetail.setState(WareTaskConstant.WAVE_STATE_PICKING);
                    }
//                    updateSoDetail(waveDetail, canBeQuantity);
                    inv.setAllotQuantity(inv.getQuantity() - canBeQuantity);
                    inv.setTransRatio(1.0);
//                    inventoryService.updateById(inv);
                    remainAllotQty -= canBeQuantity;
                }
                //记录状态
                if (ObjectUtil.equal(soDetail.getOrderQuantity(), soDetail.getAllottedQuantity())) {
                    soDetail.setState(WareTaskConstant.WAVE_STATE_ALL_ALOT);
                } else {
                    soDetail.setState(WareTaskConstant.WAVE_STATE_PICKING);
                }
            }
        }

        inventoryService.updateBatchById(inventoryList);

        if (ObjectUtil.isEmpty(outDetails)) {
            return newSo;
        }
        soDetailService.updateBatchById(newSo);
        SoMaster soMaster = soMasters.get(0);
        //todo  回传ERP
        //直发虚仓出库
        strategyErpService.resolveSo(soMaster, outDetails, new BaseAssist());
        //修改分配数量
        if (ObjectUtil.isNotEmpty(ppfList)) {
        pushErpService.UpdatePPFeedAssignedQty(ppfList);
        }


        return newSo;
    }

    @Override
    public void sendWaveState() {

    }

    @Override
    public void splitWave() {
        List<WaveMaster> list = list(new QueryWrapper<WaveMaster>()

        );
        for (WaveMaster waveMaster : list) {
            split(waveMaster.getCode());
        }
    }

    @Autowired
    private PushErpServiceImpl pushErpService;
    @Autowired
    private StrategyErpService strategyErpService;

    public void createAncestral(SoMaster soMaster, String waveCode,String userName) {
        //历史波次明细
        StringBuffer sb = new StringBuffer();
        String ancestralWaveCode = soMaster.getAncestralWaveCode();
        if (ObjectUtil.isEmpty(ancestralWaveCode)) {
            soMaster.setAncestralWaveCode(waveCode);
        } else {
            sb.append(ancestralWaveCode);
            sb.append(",");
            sb.append(waveCode);
            soMaster.setAncestralWaveCode(sb.toString());
        }
        //历史合单人
        StringBuffer userSb = new StringBuffer();
        String pastUserName = soMaster.getAncestralWaveUserName();
        if (ObjectUtil.isEmpty(pastUserName)) {
            soMaster.setAncestralWaveUserName(userName);
        } else {
            userSb.append(pastUserName);
            userSb.append(",");
            userSb.append(userName);
            List<String> newUserNames = Arrays.asList(userSb.toString().split(","));
            HashSet<String> set = new HashSet<>(newUserNames);
            soMaster.setAncestralWaveUserName(StringUtils.join(set, ","));
        }
    }


    public void createWaveAncestral(List<SoMaster> soMasterList, WaveMaster waveMaster) {
        //入库任务单号
        waveMaster.setAncestralBillNo(StringUtils.join(soMasterList.stream().map(SoMaster::getBillNo).collect(Collectors.toSet()), ","));
        //履约号
        waveMaster.setAncestralOrderBillNo(StringUtils.join(soMasterList.stream().map(SoMaster::getOrderBillNo).collect(Collectors.toSet()), ","));
        //出库任务单号
        waveMaster.setAncestralAgreement(StringUtils.join(soMasterList.stream().map(SoMaster::getTradeNo).collect(Collectors.toSet()), ","));
    }

    /**
     * 根据波次策略生成SO的查询条件
     *
     * @param waveTactic 波次策略
     * @return SoMasterCriteria
     */
    private SoMasterCriteria generateSoMasterCriteria(WaveTacticDianshang waveTactic) {
        SoMasterCriteria criteria = new SoMasterCriteria();
        //仓库
        if (waveTactic.getWareId() != null) {
            criteria.setWareId(waveTactic.getWareId());
        } else {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "波次策略无仓库属性");
        }
        //客户
        if (waveTactic.getCustomerId() != null && waveTactic.getCustomerId() != 0) {
            criteria.setCustomerId(waveTactic.getCustomerId());
        }
        //承运商
        if (waveTactic.getCarrierId() != null && waveTactic.getCarrierId() != 0) {
            criteria.setCarrierId(waveTactic.getCarrierId());
        }
        //SO类型
        if (waveTactic.getSoType() != null) {
            criteria.setSoType(waveTactic.getSoType());
        }
        //物料种类 SKU数
        if (waveTactic.getItemCount() != null) {
            criteria.setWaveItemCount(waveTactic.getItemCount());
        }
        //订单结构
        if (waveTactic.getSoStructure() != null) {
            criteria.setSoStructure(waveTactic.getSoStructure());
        }
        return criteria;
    }
}
